using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace SaToken.SaToken.util;

public class SaFoxUtil
{
    private static readonly ThreadLocal<Random> Random =
        new ThreadLocal<Random>(() => new Random(Guid.NewGuid().GetHashCode()));

    /// <summary>
    /// 生成指定长度的随机字符串
    /// </summary>
    /// <param name="length">字符串长度</param>
    /// <returns>随机字符串</returns>
    public static string GetRandomString(int length)
    {
        ArgumentOutOfRangeException.ThrowIfNegativeOrZero(length);

        const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        var sb = new StringBuilder(length);
        for (var i = 0; i < length; i++)
        {
            var index = Random.Value!.Next(chars.Length);
            sb.Append(chars[index]);
        }

        return sb.ToString();
    }

    /// <summary>
    /// 生成指定区间的随机整数（包含两端）
    /// </summary>
    /// <param name="min">最小值</param>
    /// <param name="max">最大值</param>
    /// <returns>随机整数</returns>
    public static int GetRandomNumber(int min, int max)
    {
        return Random.Value!.Next(min, max + 1);
    }


    /// <summary>
    /// 判断数组是否为 null 或空数组
    /// </summary>
    /// <typeparam name="T">数组类型</typeparam>
    /// <param name="array">数组</param>
    /// <returns>是否为空</returns>
    public static bool IsEmptyArray<T>(T[]? array)
    {
        return array == null || array.Length == 0;
    }

    /// <summary>
    /// 判断集合是否为 null 或空集合
    /// </summary>
    /// <param name="list">集合</param>
    /// <returns>是否为空</returns>
    public static bool IsEmptyList(List<object>? list)
    {
        return list == null || list.Count == 0;
    }


    /// <summary>
    /// 生成包含当前时间戳和随机整数的标记字符串
    /// </summary>
    /// <returns>标记字符串</returns>
    public static string GetMarking28()
    {
        return $"{DateTimeOffset.Now.ToUnixTimeMilliseconds()}{Random.Value!.Next(int.MaxValue)}";
    }

    /// <summary>
    /// 格式化日期为 "yyyy-MM-dd HH:mm:ss"
    /// </summary>
    /// <param name="date">日期</param>
    /// <returns>格式化后的字符串</returns>
    public static string FormatDate(DateTime date)
    {
        return date.ToString("yyyy-MM-dd HH:mm:ss");
    }

    /// <summary>
    /// 格式化日期为 "yyyy-MM-dd HH:mm:ss"
    /// </summary>
    /// <param name="dateTimeOffset">日期</param>
    /// <returns>格式化后的字符串</returns>
    public static string FormatDate(DateTimeOffset dateTimeOffset)
    {
        return dateTimeOffset.ToString("yyyy-MM-dd HH:mm:ss");
    }

    /// <summary>
    /// 格式化指定毫秒后的时间为 "yyyy-MM-dd HH:mm:ss"
    /// </summary>
    /// <param name="ms">毫秒数</param>
    /// <returns>格式化后的字符串</returns>
    public static string FormatAfterDate(long ms)
    {
        var date = DateTimeOffset.Now.AddMilliseconds(ms);
        return FormatDate(date);
    }

    /// <summary>
    /// 字符串模糊匹配（支持 * 通配符）
    /// </summary>
    /// <param name="pattern">匹配模式</param>
    /// <param name="str">待匹配字符串</param>
    /// <returns>是否匹配</returns>
    public static bool VagueMatch(string? pattern, string? str)
    {
        if (pattern == null && str == null) return true;
        if (pattern == null || str == null) return false;
        return !pattern.Contains('*') ? pattern.Equals(str) : VagueMatchMethod(pattern, str);
    }

    private static bool VagueMatchMethod(string pattern, string str)
    {
        // 场景1：模式为空 → 只有目标字符串也为空时匹配
        if (string.IsNullOrEmpty(pattern))
            return string.IsNullOrEmpty(str);

        // 预处理：压缩连续*（如"**a*b" → "*a*b"）
        var compressedPattern = CompressAsterisks(pattern);
        var strLen = str.Length;
        var patternLen = compressedPattern.Length;

        // 场景2：压缩后模式为"*" → 任何字符串都匹配
        if (compressedPattern == "*")
            return true;

        // 场景3：模式中无*（纯字符匹配）
        if (!compressedPattern.Contains('*'))
        {
            // 长度不同 → 不匹配
            if (strLen != patternLen)
                return false;
            // 逐个字符比较，不匹配则提前退出
            for (var i = 0; i < strLen; i++)
            {
                if (str[i] != compressedPattern[i])
                    return false;
            }

            return true;
        }

        // 初始化一维DP数组（空间优化）
        var dp = new bool[patternLen + 1];
        dp[0] = true; // 空str匹配空pattern

        // 初始化：处理空str与pattern的匹配（仅*可匹配）
        for (var j = 1; j <= patternLen; j++)
        {
            dp[j] = dp[j - 1] && compressedPattern[j - 1] == '*';
        }

        // 场景4.1：初始化后已匹配（整个pattern可匹配空str）
        if (strLen == 0)
            return dp[patternLen];

        // 填充DP数组，加入提前退出判断
        for (var i = 1; i <= strLen; i++)
        {
            var prev = dp[0]; // 上一行的dp[0]
            dp[0] = false; // 当前行的dp[0]（非空str无法匹配空pattern）
            var currentRowAllFalse = true; // 标记当前行是否全为false

            for (var j = 1; j <= patternLen; j++)
            {
                var current = dp[j]; // 暂存当前dp[j]（下一次迭代的prev）

                if (compressedPattern[j - 1] == '*')
                {
                    dp[j] = dp[j - 1] || current; // *匹配逻辑
                }
                else if (str[i - 1] == compressedPattern[j - 1])
                {
                    dp[j] = prev; // 字符匹配，继承上一行前一列状态
                }
                else
                {
                    dp[j] = false; // 不匹配
                }

                // 更新当前行状态：若有一个true，则不全为false
                if (dp[j])
                    currentRowAllFalse = false;

                prev = current;
            }

            // 场景4.2：当前行全为false → 后续行不可能有true，提前退出
            if (currentRowAllFalse)
                return false;

            // 场景4.3：当前已匹配整个pattern → 提前返回true
            if (dp[patternLen])
                return true;
        }

        // 最终结果
        return dp[patternLen];
    }

// 压缩连续*的辅助方法（复用之前的实现）
    private static string CompressAsterisks(string pattern)
    {
        if (string.IsNullOrEmpty(pattern))
            return pattern;

        var sb = new StringBuilder();
        var isPrevAsterisk = false;

        foreach (var c in pattern)
        {
            if (c == '*')
            {
                if (isPrevAsterisk) continue;
                sb.Append(c);
                isPrevAsterisk = true;
            }
            else
            {
                sb.Append(c);
                isPrevAsterisk = false;
            }
        }

        return sb.ToString();
    }

    /// <summary>
    /// 判断类型是否为八大包装类型
    /// </summary>
    /// <param name="type">类型</param>
    /// <returns>是否为包装类型</returns>
    public static bool IsWrapperType(Type type)
    {
        return type == typeof(int) || type == typeof(short) || type == typeof(long) || type == typeof(byte)
               || type == typeof(float) || type == typeof(double) || type == typeof(bool) || type == typeof(char);
    }

    /// <summary>
    /// 判断类型是否为基础类型（基本类型、包装类型、string）
    /// </summary>
    /// <param name="type">类型</param>
    /// <returns>是否为基础类型</returns>
    public static bool IsBasicType(Type type)
    {
        return type.IsPrimitive || IsWrapperType(type) || type == typeof(string);
    }

    

    /// <summary>
    /// 将字典转换为对象
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="map">字典</param>
    /// <param name="type">对象类型</param>
    /// <returns>转换后的对象</returns>
    public static T DictionaryToObject<T>(Dictionary<string, object>? map, Type type)
    {
        if (map == null) return default;
        if (type == typeof(Dictionary<string, object>)) return (T)(object)map;

        try
        {
            var obj = Activator.CreateInstance(type);
            foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                if (map.TryGetValue(field.Name, out object value))
                {
                    field.SetValue(obj, value);
                }
            }

            return (T)obj;
        }
        catch (Exception ex)
        {
            throw new Exception($"转换失败: {ex.Message}", ex);
        }
    }

    /// <summary>
    /// 拼接URL参数
    /// </summary>
    /// <param name="url">基础URL</param>
    /// <param name="paramStr">参数字符串（如 "id=1"）</param>
    /// <returns>拼接后的URL</returns>
    public static string JoinParam(string url, string paramStr)
    {
        if (string.IsNullOrEmpty(paramStr)) return url ?? "";
        url ??= "";

        int index = url.LastIndexOf('?');
        if (index == -1)
        {
            return $"{url}?{paramStr}";
        }

        if (index == url.Length - 1)
        {
            return $"{url}{paramStr}";
        }

        const string separator = "&";
        if (url.LastIndexOf(separator, StringComparison.Ordinal) != url.Length - 1 &&
            paramStr.IndexOf(separator, StringComparison.Ordinal) != 0)
        {
            return $"{url}{separator}{paramStr}";
        }

        return $"{url}{paramStr}";
    }

    /// <summary>
    /// 拼接URL参数
    /// </summary>
    /// <param name="url">基础URL</param>
    /// <param name="key">参数名</param>
    /// <param name="value">参数值</param>
    /// <returns>拼接后的URL</returns>
    public static string JoinParam(string url, string key, object value)
    {
        if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(key)) return url ?? "";
        return JoinParam(url, $"{key}={value}");
    }

    /// <summary>
    /// 拼接URL锚点参数
    /// </summary>
    /// <param name="url">基础URL</param>
    /// <param name="paramStr">参数字符串（如 "id=1"）</param>
    /// <returns>拼接后的URL</returns>
    public static string JoinSharpParam(string url, string paramStr)
    {
        if (string.IsNullOrEmpty(paramStr)) return url ?? "";
        url ??= "";

        var index = url.LastIndexOf('#');
        if (index == -1)
        {
            return $"{url}#{paramStr}";
        }

        if (index == url.Length - 1)
        {
            return $"{url}{paramStr}";
        }

        const string separator = "&";
        if (url.LastIndexOf(separator, StringComparison.Ordinal) != url.Length - 1 &&
            !paramStr.StartsWith(separator, StringComparison.Ordinal))
        {
            return $"{url}{separator}{paramStr}";
        }

        return $"{url}{paramStr}";
    }

    /// <summary>
    /// 拼接URL锚点参数
    /// </summary>
    /// <param name="url">基础URL</param>
    /// <param name="key">参数名</param>
    /// <param name="value">参数值</param>
    /// <returns>拼接后的URL</returns>
    public static string JoinSharpParam(string url, string key, object value)
    {
        if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(key)) return url ?? "";
        return JoinSharpParam(url, $"{key}={value}");
    }

    /// <summary>
    /// 拼接两个URL
    /// </summary>
    /// <param name="url1">第一个URL</param>
    /// <param name="url2">第二个URL</param>
    /// <returns>拼接后的URL</returns>
    public static string SpliceTwoUrl(string? url1, string? url2)
    {
        if (url1 == null) return url2 ?? "";
        if (url2 == null) return url1;
        return url2.StartsWith("http") ? url2 : $"{url1}{url2}";
    }

    /// <summary>
    /// 用逗号拼接字符串数组
    /// </summary>
    /// <param name="arr">字符串数组</param>
    /// <returns>拼接后的字符串</returns>
    public static string ArrayJoin(string[]? arr)
    {
        return arr == null || arr.Length == 0 ? "" : string.Join(",", arr);
    }

    /// <summary>
    /// URL正则表达式
    /// </summary>
    public const string UrlRegex = @"(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]";

    /// <summary>
    /// 判断字符串是否为URL
    /// </summary>
    /// <param name="str">字符串</param>
    /// <returns>是否为URL</returns>
    public static bool IsUrl(string str)
    {
        return !string.IsNullOrWhiteSpace(str) && Regex.IsMatch(str.ToLower(), UrlRegex);
    }

    

    /// <summary>
    /// 将逗号分隔的字符串转换为集合
    /// </summary>
    /// <param name="str">字符串</param>
    /// <returns>字符串集合</returns>
    public static List<string> ConvertStringToList(string str)
    {
        var list = new List<string>();
        if (string.IsNullOrWhiteSpace(str)) return list;
        list.AddRange(str.Split(',').Select(s => s.Trim()).Where(trimmed => !string.IsNullOrWhiteSpace(trimmed)));

        return list;
    }

    /// <summary>
    /// 将字符串集合转换为指定分隔符分隔的字符串
    /// </summary>
    /// <param name="source">字符串集合（可为 null 或空）</param>
    /// <param name="separator">分隔符（默认逗号）</param>
    /// <returns>分隔后的字符串；集合为 null 或空时返回空字符串</returns>
    public static string JoinStrings(IEnumerable<string>? source, string separator = ",")
    {
        return source switch
        {
            null or ICollection<string> { Count: 0 } => "",
            _ => string.Join(separator, source)
        };
    }

    /// <summary>
    /// 将字符串转换为数组（按逗号分割）
    /// </summary>
    /// <param name="str">字符串</param>
    /// <returns>字符串数组</returns>
    public static string[] ConvertStringToArray(string str)
    {
        return ConvertStringToList(str).ToArray();
    }

    /// <summary>
    /// 将数组转换为逗号分隔的字符串
    /// </summary>
    /// <param name="arr">数组</param>
    /// <returns>字符串</returns>
    public static string ConvertArrayToString(string[]? arr)
    {
        return JoinStrings(arr);
    }


    public static List<string> LogLevelList = new List<string>
        { "", "trace", "debug", "info", "warn", "error", "fatal" };

    /// <summary>
    /// 将日志等级从字符串转换为整数
    /// </summary>
    /// <param name="level">日志等级字符串</param>
    /// <returns>整数等级</returns>
    public static int TranslateLogLevelToInt(string level)
    {
        var index = LogLevelList.IndexOf(level);
        return index <= 0 || index >= LogLevelList.Count ? 1 : index;
    }

    /// <summary>
    /// 将日志等级从整数转换为字符串
    /// </summary>
    /// <param name="level">整数等级</param>
    /// <returns>日志等级字符串</returns>
    public static string TranslateLogLevelToString(int level)
    {
        return level <= 0 || level >= LogLevelList.Count ? LogLevelList[1] : LogLevelList[level];
    }

    /// <summary>
    /// 判断当前系统是否支持彩色日志
    /// </summary>
    /// <returns>是否支持</returns>
    public static bool IsCanColorLog()
    {
        var isConsoleNull = Console.In == null; // 模拟 Java System.console() 判断
        var term = Environment.GetEnvironmentVariable("TERM");

        switch (isConsoleNull)
        {
            case true when term == null:
            case false when term != null:
                return true;
            case false when term == null:
                return false;
            default:
                return isConsoleNull && false;
        }
    }

    /// <summary>
    /// 判断集合1是否包含集合2的所有元素
    /// </summary>
    /// <param name="list1">集合1</param>
    /// <param name="list2">集合2</param>
    /// <returns>是否包含</returns>
    public static bool List1ContainList2AllElement(List<string>? list1, List<string>? list2)
    {
        if (list2 == null || list2.Count == 0) return true;
        if (list1 == null || list1.Count == 0) return false;

        return list2.All(list1.Contains);
    }

    /// <summary>
    /// 判断集合1是否包含集合2的任意元素（支持任意 IEnumerable 集合）
    /// </summary>
    /// <typeparam name="T">集合元素类型</typeparam>
    /// <param name="collection1">集合1（可为 null 或空）</param>
    /// <param name="collection2">集合2（可为 null 或空）</param>
    /// <returns>是否包含</returns>
    public static bool CollectionContainsAny<T>(IEnumerable<T>? collection1, IEnumerable<T>? collection2)
    {
        // 处理 null 或空集合（提前退出）
        if (collection1 == null || collection2 == null) return false;
        // 转换为集合以避免多次枚举（如 IEnumerable 是查询时，ToList 可优化性能）
        var list1 = collection1 as ICollection<T> ?? collection1.ToList();
        var list2 = collection2 as ICollection<T> ?? collection2.ToList();
        if (list1.Count == 0 || list2.Count == 0) return false;

        // 若集合1是 HashSet，使用 Contains 效率更高（O(1)）
        if (list1 is HashSet<T> hashSet)
            return list2.Any(hashSet.Contains);
        // 普通集合使用默认 Contains（O(n)）
        return list2.Any(list1.Contains);
    }

    /// <summary>
    /// 从集合1中剔除集合2包含的元素（返回新集合，不修改原集合）
    /// </summary>
    /// <param name="list1">集合1</param>
    /// <param name="list2">集合2</param>
    /// <returns>处理后的集合</returns>
    public static List<string>? List1RemoveByList2(List<string>? list1, List<string>? list2)
    {
        if (list1 == null) return null;
        if (list1.Count == 0 || list2 == null || list2.Count == 0) return [..list1];

        var newList = new List<string>(list1);
        foreach (var item in list2)
        {
            newList.Remove(item);
        }

        return newList;
    }

    /// <summary>
    /// 检查字符串是否包含非打印ASCII字符
    /// </summary>
    /// <param name="str">字符串</param>
    /// <returns>是否包含</returns>
    public static bool HasNonPrintableAscii(string? str)
    {
        return str != null && str.Any(c => c <= 31 || c == 127);
    }
    
}